
#include <QtGui>
#include <assert.h>
#include <set>
#include <sstream>

class CodeFormat
{
public:
	static std::set<QString> m_files_exit_replaced;
	static QStringList m_files_with_exit_calls;

	static void format_indentation( const char* source, std::stringstream& target )
	{
		char* pos = (char*)source;
		char* pos_line_begin= pos;
		char* last_pos = pos;
		if( !pos )
		{
			return;
		}

		//insert new indentations according to the number of open curly braces
		int num_opening_braces = 0;
		while(*pos != '\0')
		{
			if( *pos == '\n' )
			{
				++pos;
				if( *pos == '\0' )
				{
					break;
				}

				pos_line_begin = pos;

				int minus = 0;
				if( *last_pos == 'p' )
				{
					if( strncmp( last_pos, "public:",7 )== 0 )
					{
						minus=1;
					}
					else if( strncmp( last_pos, "private:",8 )== 0 )
					{
						minus=1;
					}
					else if( strncmp( last_pos, "protected:",10 )== 0 )
					{
						minus=1;
					}
				}
				else if( *last_pos == '{' )
				{
					minus=1;
				}

				if( pos_line_begin > last_pos )
				{
					// insert tabs
					for( int i=0; i<num_opening_braces-minus; ++i ) { target << "\t"; }

					std::string current_line( last_pos,pos_line_begin-last_pos);
					target << current_line;

					while(isspace(*pos_line_begin)){
					//while(*pos_line_begin=='\t' || *pos_line_begin==' '){
						if( *pos_line_begin == '\n')
						{
							target << "\n";
						}
						++pos_line_begin;
					}
					last_pos = pos_line_begin;
					
				}
				else
				{
					// empty line
					while(*pos_line_begin=='\t' || *pos_line_begin==' '){
						++pos_line_begin;
					}
					last_pos = pos_line_begin;

				}

				if( *pos == '{' )
				{
					++num_opening_braces;
				}
				else if( *pos == '}' )
				{
					--num_opening_braces;
				}
				

			}
			else if( *pos == '{' )
			{
				
				++num_opening_braces;
			}
			else if( *pos == '}' )
			{
				

				if( pos != (char*)source )
				{
					char* pos_next = pos+1;
					if( pos_next == NULL )
					{
						break;
					}
					if( *pos_next == ';')
					{
						//

						// insert tabs
						for( int i=0; i<num_opening_braces; ++i ) { target << "\t"; }

						std::string current_line( last_pos,pos-last_pos);
						last_pos = pos;
						target << current_line;
						target << "\n";
					}
				}

				--num_opening_braces;
			}
			++pos;
		}
		std::string current_line( last_pos,pos-last_pos);
		target << current_line;
		return;
	}

	/*static bool format_indentation( QString& content )
	{
		const QChar opening_brace( '{' );
		const QChar closing_brace( '}' );
		const QChar semicolon( ';' );
		const QChar tab( '\t' );
		const QChar newline( '\n' );

		//remove old indentations
		int pos_newline=0;
		QRegExp rx_newline( "\\n[\\t ]+" );
		while( (pos_newline = rx_newline.indexIn( content, pos_newline )) != -1 )
		{
			QString complete_match = rx_newline.cap(0);
			content.replace( pos_newline, complete_match.length(), "\n" );
		}


		//insert new indentations according to the number of open curly braces
		int num_opening_braces = 0;
		int pos = 0;
		int length = content.length();
		while( pos < length )
		{
			const QChar ch = content[pos];

			if( ch == newline )
			{
				int minus = 0;
				if( length > pos+1 )
				{
					if( content[pos+1] == closing_brace )
					{
						minus = 1;
					}
				
					if( content[pos+1] == QChar('p'))
					{
						if( content.midRef(pos+1,7).compare("public:")== 0)
						{
							minus=1;
						}
						else if( content.midRef(pos+1,8).compare("private:")== 0)
						{
							minus=1;
						}
						else if( content.midRef(pos+1,10).compare("protected:")== 0)
						{
							minus=1;
						}
					}
				}
				for( int i=0; i<num_opening_braces-minus; ++i )
				{
					++pos;
					content.insert( pos, tab );
					++length;
				}
			}
			else if( ch == opening_brace )
			{

				++num_opening_braces;
			}
			else if( ch == closing_brace )
			{
				--num_opening_braces;
			}
			++pos;
		}

		//additional indentations for .cpp files 
		//if( path.endsWith(".cpp"))
		//{
		//	int pos_method=0;
		//	int pos_match=0;
		//	int replace_length = 0;
		//	QRegExp rx_method("(\\n+)[\\t ]*(("+m_name_chars+"*[\\*&]?)\\s*)?("+m_name_chars+"*)\\s*::\\s*("+m_name_chars+"+)\\s*\\("+m_arg_chars+"*\\)\\s*(:?"+m_init_chars+"*)?\\{" );
		//	while( (pos_method = rx_method.indexIn( content, pos_method )) != -1 )
		//	{
		//		pos_match=0;
		//		QString complete_match = rx_method.cap(0);
		//		while ((pos_match = complete_match.indexOf("\n",pos_match)) != -1)
		//		{
		//			if( pos_match >= rx_method.cap(1).length() && pos_match != complete_match.length()-1 && complete_match.at(pos_match+1) != opening_brace )
		//			{
		//				content.insert(pos_method+pos_match+1, tab);
		//				complete_match.insert(pos_match+1, tab);
		//				++pos_match;
		//			}
		//			++pos_match;
		//		}
		//		pos_method += complete_match.length();
		//	}
		//}

		
		return true;
	}
	// find curly braces and put each into a single line
	static bool format_curly_braces (QString& content)
	{
		const QChar opening_brace( '{' );
		const QChar closing_brace( '}' );
		const QChar semicolon( ';' );
		const QChar newline( '\n' );

		int pos = 0;
		int length = content.length();
		while( pos < length )
		{
			const QChar ch = content[pos];
			QString test ="";
			test.append(ch);

			if (ch == opening_brace || ch == closing_brace)
			{
				if(pos > 0)
				{
					if (content[pos-1] != newline)
					{
						int current_pos = pos;
						QString beginOfLine = "";
						while (current_pos >= 0 && content[current_pos] != newline)
						{
							beginOfLine.prepend(content[current_pos]);
							--current_pos;
						}
						int newline_pos = 0;
						QRegExp rx_startOfLine("([\\t ]+)[\\{\\}]{1,1}");
						if ((newline_pos = rx_startOfLine.indexIn(beginOfLine, newline_pos)) != -1)
						{
							QString complete_match = rx_startOfLine.cap(0);
							QString before_brace = rx_startOfLine.cap(1);
							content.replace(current_pos+newline_pos+1, before_brace.length(), "");
							beginOfLine.replace(newline_pos, before_brace.length(), "");
							length -= before_brace.length();
							pos -= before_brace.length();
						}
						if (content[pos-1] != newline)
						{
							content.insert(pos, newline);
							++pos;
							++length;
						}
					}
				}
				if (length > pos+1)
				{
					if (content[pos+1] != newline)
					{
						int current_pos = pos;
						QString restOfLine = "";
						while (length > current_pos+1 && content[current_pos] != newline)
						{
							restOfLine.append(content[current_pos]);
							++current_pos;
						}
						int newline_pos = 0;
						QRegExp rx_endOfLine("[\\{\\}]{1,1}([\\t ]+)");
						if ((newline_pos = rx_endOfLine.indexIn(restOfLine, newline_pos)) != -1)
						{
							QString complete_match = rx_endOfLine.cap(0);
							QString behind_brace = rx_endOfLine.cap(1);
							content.replace(current_pos-restOfLine.length()+newline_pos+1, behind_brace.length(), "");
							restOfLine.replace(newline_pos+1, behind_brace.length(), "");
							length -= behind_brace.length();
						}
						if (content[pos+1] != newline)
						{
							if (content[pos+1] != semicolon)
							{
								content.insert(pos+1, newline);
								++pos;
								++length;
							}
						}
					}
				}
			}
			++pos;
		}
		return true;
	}
	*/

	static bool remove_newLines ( QString& content, QString path )
	{
		// remove all empty lines
		int pos_newline=0;
		QRegExp rx_newline( "\n[\t ]*\n" );
		while( (pos_newline = rx_newline.indexIn( content, pos_newline )) != -1 )
		{
			QString complete_match = rx_newline.cap(0);
			content.replace( pos_newline, complete_match.length(), "\n" );
		}

		//insert empty line after includes
		int include_pos = content.lastIndexOf("#include");
		int next_newline_pos = content.indexOf("\n", include_pos);
		if( next_newline_pos != -1)
		{
			content.insert(next_newline_pos, "\n");
		}

		//insert empty line after class declarations;
		QRegExp rx_class("\\n[\\t ]*class[\\t ]+[A-Za-z0-9_]+\\;[\\t ]*\\n");
		int class_pos = content.lastIndexOf(rx_class);
		if( class_pos!= -1)
		{
			content.insert(class_pos+rx_class.cap(0).length(), "\n");
		}

		// insert empty lines after labels
		QRegExp rx_label("\\n[\\t ]*(public|private|protected)[\\t ]*\\:[\\t ]*\\n");
		int pos = 0;
		while (pos < content.length())
		{
			pos = rx_label.indexIn(content, pos);
			if( pos == -1)
			{
				break;
			}
			content.insert(pos, "\n");
			pos += rx_label.matchedLength();
		}

		int define_pos= 0;
		while ( define_pos < content.length() && define_pos != -1)
		{
			define_pos = content.indexOf("#define", define_pos);
			if( define_pos != -1)
			{
				next_newline_pos = content.indexOf("\n", define_pos);
				if( next_newline_pos != -1)
				{
					content.insert(next_newline_pos, "\n");
					++define_pos;
				}
				++define_pos;
			}
		}

		// insert empty line before #....
		int ifdef_pos= 0;
		QRegExp rx_ifdef("(\\n+)[\\t ]*#(ifdef|ifndef|else|elif)");
		while ( ifdef_pos < content.length() && ifdef_pos != -1)
		{
			ifdef_pos = content.indexOf(rx_ifdef, ifdef_pos);
			if( ifdef_pos != -1)
			{
				content.replace(ifdef_pos, rx_ifdef.cap(1).length(),"\n\n");
				if( rx_ifdef.cap(1).length() == 1)
				{
					++ifdef_pos;
				}
				++ifdef_pos;
			}
		}

		// insert empty line after #....
		int endif_pos= 0;
		QRegExp rx_endif("(#endif[\\t ]*)(\\n+)");
		while ( endif_pos < content.length() && endif_pos != -1)
		{
			endif_pos = content.indexOf(rx_endif, endif_pos);
			if( endif_pos != -1)
			{
				content.replace(endif_pos + rx_endif.cap(1).length(), rx_endif.cap(2).length(),"\n\n");
				if( rx_endif.cap(1).length() == 1)
				{
					++endif_pos;
				}
				++endif_pos;
			}
		}

		//insert empty lines before method
		int pos_method=0;

		QString m_name_chars = "[a-zA-Z0-9_~]";
		QString m_arg_chars = "[a-zA-Z0-9_\\s,&\\*]";
		QString m_init_chars = "[&\\*a-zA-Z0-9_\\s,\\.\\(\\)]";

		QRegExp rx_method("(\\n+[\\t ]*)(((((const|virtual)[\\t ]*)?[a-zA-Z0-9_]*)([\\t ]*)([\\*&]?))(\\s+))?("+m_name_chars+"*)(\\s*::)(\\s*)("+m_name_chars+"+)\\s*\\("+m_arg_chars+"*\\)\\s*(const)?\\s*(:?"+m_init_chars+"*)?\\{" );
		while( (pos_method = rx_method.indexIn( content, pos_method )) != -1 )
		{
			QString complete_match = rx_method.cap(0);

			QString cap1 = rx_method.cap(1); //mandatory new line + possible whitespaces
			QString cap2 = rx_method.cap(2); //complete return type
			QString cap3 = rx_method.cap(3); //complete return type without trailing whitespace
			QString cap4 = rx_method.cap(4); //label and return type ends before * or &
			QString cap5 = rx_method.cap(5); //label of return type with trailing whitespace
			QString cap6 = rx_method.cap(6); //label of return type 
			QString cap7 = rx_method.cap(7); //whitespaces before & or *
			QString cap8 = rx_method.cap(8); //& or *
			QString cap9 = rx_method.cap(9); //new lines + whitespaces before mehtod name
			QString cap10 = rx_method.cap(10); //class name
			QString cap11 = rx_method.cap(11); // evtl. space and :: before class name and constructor name
			QString cap12 = rx_method.cap(12); // evtl. newline between  class name and constructor name
			QString cap13 = rx_method.cap(13); //method name
			QString cap14 = rx_method.cap(14); //method arguments
			QString cap15 = rx_method.cap(15); //const label
			QString cap16 = rx_method.cap(16); //variable  initialization

			if( !cap12.isEmpty() )
			{
				content.replace(pos_method+cap1.length()+cap2.length()+cap10.length()+cap11.length(), cap12.length(), "" );
			}
			if( !cap9.isEmpty())
			{
				content.replace(pos_method + cap1.length() + cap3.length(), cap9.length(), " ");
			}
			if( !cap7.isEmpty() && !cap8.isEmpty())
			{
				content.replace(pos_method + cap1.length() + cap4.length(), cap7.length(), "");
			}

			content.replace(pos_method, cap1.length(), "\n\n" );

			pos_method += complete_match.length()- cap1.length() - cap6.length() - cap8.length() + 3;


			/*QRegExp rx_method("(\\n+)([\\t ]*)(("+m_name_chars+"*[\\*& ]*)(\\s+))?("+m_name_chars+"*)\\s*::\\s*("+m_name_chars+"+)\\s*\\("+m_arg_chars+"*\\)\\s*(const)?\\s*(:?"+m_init_chars+"*)?\\{" );
			while( (pos_method = rx_method.indexIn( content, pos_method )) != -1 )
			{
			QString complete_match = rx_method.cap(0);

			QString cap1 = rx_method.cap(1);
			QString cap2 = rx_method.cap(2);
			QString cap3 = rx_method.cap(3);
			QString cap4 = rx_method.cap(4);
			QString cap5 = rx_method.cap(5);
			QString cap6 = rx_method.cap(6);
			QString cap7 = rx_method.cap(7);
			QString cap8 = rx_method.cap(8);
			QString cap9 = rx_method.cap(9);
			QString cap10 = rx_method.cap(10);

			if( !rx_method.cap(5).isEmpty())
			{
			content.replace(pos_method + rx_method.cap(1).length() + rx_method.cap(2).length() + + rx_method.cap(4).length(), rx_method.cap(5).length(), " ");
			}
			content.replace(pos_method, rx_method.cap(1).length(), "\n\n" );

			pos_method += complete_match.length()- rx_method.cap(1).length() + rx_method.cap(5).length()+ 3;
			*/

		}
		return true;
	}

	static bool insert_loop_parantheses( QString& content)//, QTextEdit* txt_out_warning )
	{
		const QChar opening_brace('{');
		const QChar closing_brace('}');
		const QChar semicolon(';');

		QMap<int, QString> loop_pos;
		QRegExp rx_loop("\\b((else[\\s]*)?if|for|while)\\s*\\(");

		int pos = 0;
		while ((pos = rx_loop.indexIn(content, pos)) != -1)
		{
			QString cap1 = rx_loop.cap(1);
			QString cap2 = rx_loop.cap(2);
			if ( cap2.startsWith("else"))
			{
				int debug = 0;
			}

			loop_pos.insert(pos, rx_loop.cap(1));
			pos += rx_loop.matchedLength();
		}

		QRegExp	rx_loop2("\\s(else(?!([\\s]*if)))\\s");
		pos = 0;
		while ((pos = rx_loop2.indexIn(content, pos)) != -1)
		{
			QString cap1 = rx_loop2.cap(1);
			loop_pos.insert(pos+1, rx_loop2.cap(1));
			pos += rx_loop2.matchedLength();
		}


		/*	QMapIterator<int, QString> it2(loop_pos);
		while( it2.hasNext())
		{
		it2.next();
		txt_out_warning->append((QString::number(it2.key())+" - " + it2.value()));
		QApplication::processEvents();
		}*/

		int added_chars = 0;
		int added_chars_nested = 0;
		int add_chars_later = 0;
		int openingbrace_pos;
		int closingbrace_pos;
		int insert_openingbrace_pos;
		int insert_closingbrace_pos;
		int insert_nested_closingbrace_pos = 0;
		int num_last_nested_loops = 0;
		int added_chars_last_nested_loop = 0;
		bool add_chars_nested_again = false;
		bool no_change = false;
		bool braces_exist = false;
		bool iter_loops = false;
		bool found_insert_opening_brace;
		bool last_nested_loop = false;
		bool nested_loop;
		bool doing_nested_loops = false;
		bool doing_last_nested_loop = false;
		int nested_loops = 0;
		int max_nested_loops = 0;
		QList<int> nested_closingbrace_pos;

		QMapIterator<int, QString> it(loop_pos);
		if( it.hasNext())
		{
			it.next();
			iter_loops = true;
		}

		while( iter_loops)
		{
			//txt_out_warning ->append("\n\n" + content);
			//QApplication::processEvents();

			QString loop = it.value();
			int loop_start_pos = it.key()+added_chars;
			//only_space_after_loop_head = true;
			nested_loop = false;
			braces_exist = false;
			no_change = false;
			insert_closingbrace_pos = 0;
			closingbrace_pos = 0;
			found_insert_opening_brace = false;

			if (add_chars_nested_again)
			{
				int peekNextKey = 0;
				if (it.hasNext())
				{
					peekNextKey = it.peekNext().key() + added_chars;
				}
				while (!nested_closingbrace_pos.isEmpty() && nested_closingbrace_pos.first() < peekNextKey )
				{
					nested_closingbrace_pos.removeFirst();
				}

				if (nested_closingbrace_pos.isEmpty())
				{
					added_chars += add_chars_later;
					add_chars_nested_again = false;
					add_chars_later = 0;
				}
			}


			if (loop == "else")
			{
				pos = it.key()+added_chars + added_chars_last_nested_loop + 4;
			}
			else
			{
				pos = find_matching_char( content, it.key() + added_chars + added_chars_last_nested_loop, '(', ')') + 1;
			}
			while( pos < content.length())
			{
				if( content.at(pos).isSpace())
				{
					++pos;
					continue;
				}
				else if( !found_insert_opening_brace && content.at(pos) == opening_brace)
				{
					openingbrace_pos = pos;
					closingbrace_pos = find_matching_char( content, pos, '{', '}');
					braces_exist = true;
					break;
				}
				if (!found_insert_opening_brace && it.hasNext() && !doing_nested_loops)
				{
					int debug = it.peekNext().key() + added_chars;
					if( pos == it.peekNext().key() + added_chars + added_chars_last_nested_loop)
					{
						++nested_loops;
						nested_loop = true;
						break;
					}
				}
				if ( content.at(pos) == semicolon && !doing_nested_loops )
				{
					if (!found_insert_opening_brace)
					{
						no_change = true;
						break;
					}
					insert_closingbrace_pos = pos + 1;
					break;
				}
				else 
				{
					if( !found_insert_opening_brace)
					{
						insert_openingbrace_pos = pos;
						found_insert_opening_brace = true;
						if( doing_nested_loops)
						{
							insert_closingbrace_pos = insert_nested_closingbrace_pos;
							break;
						}
					}
					++ pos;
				}
			}


			if (nested_loop == false && nested_loops != 0 && !doing_nested_loops)
			{
				last_nested_loop = true;
			}
			if (braces_exist && !last_nested_loop || no_change)
			{
				if( it.hasNext())
				{
					it.next();
				}
				else
				{
					iter_loops = false;
				}
				continue;
			}
			if (nested_loops == 0 && !braces_exist || doing_nested_loops || (last_nested_loop && !braces_exist))
			{
				content.insert( insert_openingbrace_pos, "\n{\n");
				content.insert( insert_closingbrace_pos+3, "\n}\n");
				insert_nested_closingbrace_pos += 6;

				if( !doing_nested_loops && !last_nested_loop)
				{
					added_chars += 6;
					if( it.hasNext())
					{
						it.next();
					}
					else
					{
						iter_loops = false;
					}
					continue;
				}
				else
				{
					added_chars_nested += 6;
				}
				if (last_nested_loop)
				{
					added_chars_last_nested_loop = 6;
				}
			}
			if (nested_loops > 0 || doing_last_nested_loop)
			{
				if (doing_last_nested_loop)
				{
					for (int i = 0; i < max_nested_loops + num_last_nested_loops +2 ; i++)
					{
						if(it.hasNext())
						{
							it.next();
							QString debug = it.value();
						}
						else
						{
							iter_loops = false;
							continue;
						}
					}
					num_last_nested_loops = 0;

					if (it.key() + added_chars < insert_nested_closingbrace_pos)
					{
						nested_closingbrace_pos.prepend(insert_nested_closingbrace_pos);
						add_chars_later += added_chars_nested / 2;
						added_chars += add_chars_later;
						add_chars_nested_again = true;
					}
					else
					{
						added_chars += added_chars_nested;
					}
					nested_loops = 0;
					max_nested_loops = 0;
					added_chars_nested = 0;
					doing_last_nested_loop = false;
					doing_nested_loops = false;
					continue;
				}
				if (last_nested_loop)
				{
					if (closingbrace_pos > insert_closingbrace_pos)
					{
						insert_nested_closingbrace_pos = closingbrace_pos+1;
					}
					else
					{
						insert_nested_closingbrace_pos = insert_closingbrace_pos + added_chars_last_nested_loop;
					}
					if( it.hasNext())
					{
						//					if(((it.value()=="if") || (it.value()=="else if")) && ((it.peekNext().value()=="else") || (it.peekNext().value()=="else if")))
						pos = insert_nested_closingbrace_pos;
						while (pos < content.length() && content.at(pos).isSpace())
						{
							++pos;
						}
						int debug = it.peekNext().key() ;
						if ((pos == it.peekNext().key() +  added_chars + added_chars_last_nested_loop ) && it.value().contains("if") && it.peekNext().value().contains("else"))
						{
							it.next();
							//insert_nested_closingbrace_pos = 0;
							++num_last_nested_loops;
							continue;
						}
					}
					it.previous();
					for( int i = 0; i < num_last_nested_loops; i++)
					{
						it.previous();
					}
					max_nested_loops = nested_loops;
					doing_nested_loops = true;
					last_nested_loop = false;
					added_chars_last_nested_loop = 0;

				}
				if (doing_nested_loops)
				{
					it.previous();
					--nested_loops;
					if (nested_loops == 0)
					{
						doing_last_nested_loop = true;
					}
					continue;
				}
				else
				{
					it.next();
				}
			}
			else 
			{
				if( it.hasNext())
				{
					it.next();
				}
				else
				{
					iter_loops = false;
				}
			}
		}
		//	txt_out_warning ->append("\n\n" + content);
		//	QApplication::processEvents();
		return true;
	}

	static bool remove_comments( QString& content )
	{
		const QChar slash( '/' );
		const QChar star( '*' );
		const QChar newline( '\n' );

		int pos = 0;
		int comment_begin = 0;
		int length = content.length();
		bool slash_before = false;
		bool star_before = false;
		bool inside_comment = false;
		bool inside_single_line_comment = false;
		while( pos < length )
		{
			QChar ch = content[pos];

			if( slash_before )
			{
				if( ch == star )
				{
					inside_comment = true;
					comment_begin = pos-1;
					//ch = ' ';
					//content[pos] = ' ';
					//content[pos-1] = ' ';

					++pos;
					while( pos < length )
					{
						if( content[pos] == star )
						{
							if( pos+1 >= length )
							{
								break;
							}
							if( content[pos+1] == slash )
							{
								ch = ' ';
								//content[pos] = ' ';
								//content[pos+1] = ' ';
								int length_comment = pos - comment_begin + 2;
								content.remove( comment_begin, length_comment );
								pos = comment_begin;
								length = content.length();
								inside_comment = false;
								star_before = false;
								slash_before = false;
								break;
							}
						}
						//ch = ' ';
						//content[pos] = ' ';
						++pos;
					}



				}
				else if( ch == slash )
				{
					assert( !inside_single_line_comment );
					assert( !inside_comment );

					// inside single-line-comment
					//content[pos-1] = ' ';
					comment_begin = pos-1;
					inside_single_line_comment = true;

					while( pos < length )
					{
						if( content[pos] == newline )
						{
							slash_before = false;
							star_before = false;

							int length_comment = pos - comment_begin;
							content.remove( comment_begin, length_comment );
							pos = comment_begin;
							length = content.length();
							ch = ' ';
							inside_single_line_comment = false;

							break;
						}

						//content[pos] = ' ';
						++pos;
					}

				}
			}
			if( star_before )
			{
				if( ch == slash )
				{
					assert( 0 );
				}
			}
			if( ch == slash )
			{
				slash_before = true;
			}
			else
			{
				slash_before = false;
			}

			if( ch == star )
			{
				star_before = true;
			}
			else
			{
				star_before = false;
			}

			if( inside_single_line_comment )
			{
				assert( 0 );

			}
			if( inside_comment )
			{
				//ch = ' ';
				//content[pos] = ' ';
				assert( 0 );
			}
			++pos;
		}



		return true;
	}

	static bool remove_directory_recursiveley( QDir &dir )
	{
		bool has_err = false;
		if( dir.exists() )//QDir::NoDotAndDotDot
		{
			QFileInfoList entries = dir.entryInfoList( QDir::NoDotAndDotDot | QDir::Dirs | QDir::Files );

			for( int idx = 0; idx < entries.size(); ++idx )
			{
				QFileInfo entryInfo = entries[idx];
				QString path = entryInfo.absoluteFilePath();
				if( entryInfo.isDir() )
				{
					QDir remove_recursive( path );
					has_err = remove_directory_recursiveley( remove_recursive );
				}
				else
				{
					QFile file(path);
					if( !file.remove() )
					{
						has_err = true;
					}
				}
			}
			if( !dir.rmdir( dir.absolutePath() ) )
			{
				has_err = true;
			}
		}
		return(has_err);
	}

	// better solution: read dir recusively, store all filenames and path in a map
	// search only the map
	static bool find_file_recursively ( QString path, QString find_filename, QString& path_found )
	{
		QStringList more;
		QStringList::Iterator it;

		QDir dir( path );
		more = dir.entryList( QDir::Files );
		for ( it = more.begin() ; it != more.end() ; ++it )
		{
			QString filename = *it;
			if( filename == find_filename )
			{
				path_found = path + "/";
				return true;
			}
		}

		more = dir.entryList( QDir::Dirs );
		for ( it = more.begin() ; it != more.end() ; ++it )
		{
			QString dirname = *it;
			if( dirname == "." || dirname == ".." )
			{
				continue;
			}
			QString subdir = QDir::cleanPath( path + "/" + *it );
			if( find_file_recursively( subdir, find_filename, path_found ) )
			{
				return true;
			}
		}
		return false; // nothing found
	}
	static bool scan_map_from_dir( QString path, std::map<QString,QString>& map, std::map<QString,QString>& map_path, QTextEdit* txt_out_warning )
	{
		QStringList more;
		QStringList::Iterator it;

		QDir dir( path );
		more = dir.entryList( QDir::Files );
		for ( it = more.begin() ; it != more.end() ; ++it )
		{
			QString filename = *it;
			map.insert( std::pair<QString,QString>(filename,path+"/") );
			map_path.insert( std::pair<QString,QString>(QDir::cleanPath(path+"/"+filename),filename) );
		}

		more = dir.entryList( QDir::Dirs );
		for ( it = more.begin() ; it != more.end() ; ++it )
		{
			QString dirname = *it;
			if( dirname == "." || dirname == ".." )
			{
				continue;
			}
			QString subdir = QDir::cleanPath( path + "/" + *it );
			scan_map_from_dir( subdir, map, map_path, txt_out_warning );
		}
		return true; // nothing found
	}


	bool copy_including_path( QString src, QString dest )
	{
		QStringList parts = dest.split( "/" );
		if( parts.count() < 1 )
		{
			return false;
		}

		QString path_folders_dest;
		//const QString filename_proj = parts[parts.count()-1];
		for( int i=0; i<parts.count()-1; ++i )
		{
			path_folders_dest += parts[i] + "/";
		}

		QDir dir_dest( path_folders_dest );
		dir_dest.mkpath( path_folders_dest );
		QFile::copy( src, dest );
		return true;
	}



	static void replace_exit( QString& file_content, QString path )
	{
		if( path.endsWith("main.cpp"))
		{
			return;
		}

		int pos_exit = 0;
		QRegExp rx_exit1("::exit\\s*\\(");
		while( (pos_exit = rx_exit1.indexIn( file_content, pos_exit )) != -1 )
		{
			QString complete_match = rx_exit1.cap(0);
			file_content.replace( complete_match, "exit(" );
		}

		pos_exit = 0;
		QRegExp rx_exit("exit\\s*\\(\\s*([\\d+]*)\\s*\\)");
		while( (pos_exit = rx_exit.indexIn( file_content, pos_exit )) != -1 )
		{
			QString complete_match = rx_exit.cap(0);
			if( path.endsWith( ".cpp" ) )
			{
				file_content.replace( complete_match, "throw 1" );
				m_files_exit_replaced.insert( path );
			}
			else
			{
				m_files_with_exit_calls << path;
				pos_exit += rx_exit.matchedLength();
			}
		}
	}

	int find_closing_brace( QString& file_content, int start )
	{
		const QChar opening_brace( '{' );
		const QChar closing_brace( '}' );
		const QChar begin_ch = file_content[start];
		//if( begin_ch != opening_brace )
		//{
		//	return -1;
		//}
		int num_opening_braces = 1;

		int pos = start + 1;
		const int length = file_content.length();
		while( pos < length )
		{
			const QChar ch = file_content[pos];
			if( ch == opening_brace )
			{
				++num_opening_braces;
			}
			else if( ch == closing_brace )
			{
				--num_opening_braces;
			}

			if( num_opening_braces == 0 )
			{
				return pos;
			}
			++pos;
		}
		return -1;
	}

	static int find_opening_brace( QString& file_content, int start )
	{
		const QChar opening_brace( '{' );
		int pos = start + 1;
		const int length = file_content.length();
		while( pos < length )
		{
			if( file_content[pos] == opening_brace )
			{
				return pos;
			}
			++pos;
		}
		return -1;
	}

	static int find_matching_char( const QString& file_content, int start, const char opening_char, const char closing_char )
	{
		int num_opening_chars = -1;
		int pos = start;
		int length = file_content.length();
		while( pos < length )
		{
			QChar ch = file_content[pos];
			if( ch == opening_char )
			{
				if( num_opening_chars > 0)
				{
					++num_opening_chars;
				}
				else
				{
					num_opening_chars = 1;
				}
			}
			else if( ch == closing_char )
			{
				--num_opening_chars;
			}

			if( num_opening_chars == 0 )
			{
				return pos;
			}
			++pos;
		}
		return -1;
	}

	static int find_next_semicolon( QString& file_content, int start )
	{
		const QChar semicolon( ';' );
		const QChar begin_ch = file_content[start];
		int pos = start + 1;
		const int length = file_content.length();
		while( pos < length )
		{
			const QChar ch = file_content[pos];
			if( ch == semicolon )
			{
				break;
			}
			++pos;
		}
		return pos;
	}


	static bool make_comments_whitespace( QString& content )
	{
		const QChar slash( '/' );
		const QChar star( '*' );
		const QChar newline( '\n' );

		int pos = 0;
		const int length = content.length();
		bool slash_before = false;
		bool star_before = false;
		bool inside_comment = false;
		while( pos < length )
		{
			QChar ch = content[pos];

			if( slash_before )
			{
				if( ch == star )
				{
					inside_comment = true;
					ch = ' ';
					content[pos] = ' ';
					content[pos-1] = ' ';

					++pos;
					while( pos < length )
					{
						if( content[pos] == star )
						{
							if( pos+1 >= length )
							{
								break;
							}
							if( content[pos+1] == slash )
							{
								ch = ' ';
								content[pos] = ' ';
								content[pos+1] = ' ';
								inside_comment = false;
								star_before = false;
								slash_before = false;
								break;
							}
						}
						ch = ' ';
						content[pos] = ' ';
						++pos;
					}



				}
				else if( ch == slash )
				{
					if( inside_comment )
					{
					}
					else
					{
						// inside single-line-comment
						content[pos-1] = ' ';

						while( pos < length )
						{
							if( content[pos] == newline )
							{
								slash_before = false;
								star_before = false;
								break;
							}
							ch = ' ';
							content[pos] = ' ';
							++pos;
						}
					}
				}
			}
			if( star_before )
			{
				if( ch == slash )
				{
					assert( 0 );
				}
			}
			if( ch == slash )
			{
				slash_before = true;
			}
			else
			{
				slash_before = false;
			}

			if( ch == star )
			{
				star_before = true;
			}
			else
			{
				star_before = false;
			}

			if( inside_comment )
			{
				ch = ' ';
				content[pos] = ' ';
			}
			++pos;
		}
		return true;
	}
};
